package com.nlgc365.designpattern.Chapter04_Pattern.Creation.P01_Singleton.Usage.IDGenerators;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 单例模式-饱汉式
 * 功能: ID自增生成器
 * 通过添加volatile, 防止指令重排序.
 */
public class IdGenerator5 {

    private AtomicLong atomicLong = new AtomicLong(0);

    private static volatile IdGenerator5 idGenerator; // 这里添加了volatile, 目的: 防止CPU对涉及该变量的操作进行指令重排

    //私有构造函数
    private IdGenerator5() {
    }

    //如果还没有创建实例才创建
    public static IdGenerator5 getInstance() {
        //双重检测, 目的, 仅仅在需要创建实例的时候加锁
        if (idGenerator == null) {
            synchronized (IdGenerator5.class) {//为什么要双层检测: 因为第一次检测的时候, 可能多个线程同时都判断为null, 于是都在等待该处等待锁
                if (idGenerator == null) {
                    idGenerator = new IdGenerator5(); // 存在问题: 这里可能存在CPU重排序 --> 在版本5中添加volatile
                }
            }
        }
        return idGenerator;
    }

    /**
     * 生成自增ID
     *
     * @return 返回ID
     */
    public long getId() {
        return atomicLong.getAndIncrement();
    }
}
